package gamelogic

import (
	"encoding/json"
	"math"
	"server_cluster/common/logger"
	"server_cluster/common/tools"
	"server_cluster/logic/db"
	"server_cluster/logic/game_config"
	"server_cluster/logic/sharemem"
	"sync/atomic"
	"time"

	"gorm.io/gorm"
	"gorm.io/gorm/clause"
)

type MD_item_status struct {
	Normal  [sharemem.USER_ITEM_NORMAL]uint32
	Special [sharemem.USER_ITEM_SPECIAL]uint32
}

type MD_status struct {
	gem_value            int32
	update_user          uint32
	update_role          [sharemem.ROLE_MAX]uint32
	update_item          MD_item_status
	update_equip         [sharemem.USER_EQUIP]uint32
	update_equip_jewel   [sharemem.USER_EQUIP_JEWEL]uint32
	update_team          [sharemem.TEAM_MAX]uint32
	update_mail          [sharemem.MAIL_MAX]uint32
	update_home          uint32
	update_home_building [sharemem.BUILDING_MAX]uint32
}

func MD_user(tt *gorm.DB, shm_user *sharemem.User, ss *MD_status) error {
	ss.update_user = 0
	if shm_user.Id.NewVal != shm_user.Id.OldVal && shm_user.Created > 0 {
		// insert
		create_time := tools.Timestamp2time(shm_user.Created)
		update_time := tools.Timestamp2time(shm_user.LastOfflineTime)
		user := &db.DbUser{
			Id:      shm_user.Id.NewVal,
			Name:    shm_user.GetName(),
			Level:   shm_user.Level,
			Server:  int16(game_config.GetConfig().ServerId),
			Created: &create_time,
			Updated: &update_time,
		}
		err := tt.Create(user).Error
		if err != nil {
			return err
		}
		ss.update_user = math.MaxUint32
	} else if shm_user.Id.Status != 0 {
		// update 字段Gem单独特殊处理 这里不更新
		user_fields := make(map[string]interface{}, 9)
		user_fields["name"] = shm_user.GetName()
		update_time := tools.Timestamp2time(shm_user.LastOfflineTime)
		user_fields["gold"] = shm_user.Gold
		user_fields["level"] = shm_user.Level
		user_fields["exp"] = shm_user.Exp
		user_fields["server"] = game_config.GetConfig().ServerId
		user_fields["updated"] = &update_time

		err := tt.Model(&db.DbUser{}).Where("id = ?", shm_user.Id.NewVal).Updates(user_fields).Error
		if err != nil {
			return err
		}
		ss.update_user = shm_user.Id.Status
	}
	// 处理user表的Gem字段
	ss.gem_value = shm_user.Gem.NewVal - shm_user.Gem.OldVal
	if ss.gem_value != 0 {
		field_name := "gem"
		nkey := field_name + " + ?"
		err := tt.Model(&db.DbUser{}).Where("id = ?", shm_user.Id.NewVal).Update(field_name, gorm.Expr(nkey, ss.gem_value)).Error
		if err != nil {
			return err
		}
	}
	return nil
}

func MD_user_role(tt *gorm.DB, shm_user *sharemem.User, ss *MD_status) error {
	for j := 0; j < sharemem.ROLE_MAX; j++ {
		ss.update_role[j] = 0
		if shm_user.Role[j].Id.NewVal != shm_user.Role[j].Id.OldVal {
			// insert
			unlockTalent, err := json.Marshal(shm_user.Role[j].TalentList)
			if err != nil {
				return err
			}
			unlockCaptainSkill, err := json.Marshal(shm_user.Role[j].CaptainSkillList)
			if err != nil {
				return err
			}
			user_role := &db.DbRole{
				Id:                 shm_user.Role[j].Id.NewVal,
				Uid:                shm_user.Id.NewVal,
				Level:              shm_user.Role[j].Level,
				Exp:                shm_user.Role[j].Exp,
				Promote:            shm_user.Role[j].Promote,
				Star:               shm_user.Role[j].Star,
				UnlockTalent:       string(unlockTalent),
				CurrEnergy:         shm_user.Role[j].CurrEnergy,
				CurrHp:             shm_user.Role[j].CurrHp,
				UnlockCaptainSkill: string(unlockCaptainSkill),
			}
			err = tt.Create(user_role).Error
			if err != nil {
				return err
			}
			ss.update_role[j] = math.MaxUint32
		} else if shm_user.Role[j].Id.Status != 0 {
			// update
			unlockTalent, err := json.Marshal(shm_user.Role[j].TalentList)
			if err != nil {
				return err
			}
			unlockTalentStr := string(unlockTalent)
			unlockCaptainSkill, err := json.Marshal(shm_user.Role[j].CaptainSkillList)
			if err != nil {
				return err
			}
			unlockCaptainSkillStr := string(unlockCaptainSkill)
			fields := make(map[string]interface{}, 3)
			fields["level"] = shm_user.Role[j].Level
			fields["exp"] = shm_user.Role[j].Exp
			fields["promote"] = shm_user.Role[j].Promote
			fields["star"] = shm_user.Role[j].Star
			fields["unlock_talent"] = &unlockTalentStr
			fields["curr_energy"] = shm_user.Role[j].CurrEnergy
			fields["curr_hp"] = shm_user.Role[j].CurrHp
			fields["unlock_captain_skill"] = &unlockCaptainSkillStr

			err = tt.Model(&db.DbRole{}).Where("id = ? AND uid = ?", shm_user.Role[j].Id.NewVal, shm_user.Id.NewVal).Updates(fields).Error
			if err != nil {
				return err
			}
			ss.update_role[j] = shm_user.Role[j].Id.Status
		}
	}
	return nil
}

func MD_user_item(tt *gorm.DB, shm_user_item *sharemem.Item, uid int64, index int16, ss *uint32) error {
	var end_time, update_time time.Time
	var etr, utr *time.Time
	*ss = 0
	if shm_user_item.Id.NewVal != shm_user_item.Id.OldVal {
		if shm_user_item.Id.NewVal > 0 {
			// insert
			etr = nil
			utr = nil
			if shm_user_item.EndTime != 0 {
				end_time = tools.Timestamp2time(shm_user_item.EndTime)
				etr = &end_time
			}
			if shm_user_item.CdEndTime != 0 {
				end_time = tools.Timestamp2time(shm_user_item.CdEndTime)
				utr = &update_time
			}
			user_item := &db.DbItem{
				Id:      shm_user_item.Id.NewVal,
				Uid:     uid,
				Cell:    index,
				Type:    shm_user_item.Type,
				Num:     shm_user_item.Num,
				Day:     shm_user_item.Day,
				CdTime:  utr,
				EndTime: etr,
			}
			err := tt.Create(user_item).Error
			if err != nil {
				return err
			}
		}
		if shm_user_item.Id.OldVal > 0 {
			// delelte
			user_item2 := &db.DbItem{
				Id:   shm_user_item.Id.OldVal,
				Uid:  uid,
				Cell: index,
				Type: shm_user_item.Type,
			}
			err := tt.Where("id = ? and uid = ? and cell = ? and type = ?", shm_user_item.Id.OldVal, uid, index, shm_user_item.Type).Delete(user_item2).Error
			if err != nil {
				return err
			}
		}
		*ss = math.MaxUint32
	} else if shm_user_item.Id.Status != 0 {
		// update
		fields := make(map[string]interface{}, 3)
		fields["num"] = shm_user_item.Num
		if shm_user_item.EndTime != 0 {
			fields["end_time"] = tools.Timestamp2time(shm_user_item.EndTime)
		}
		if shm_user_item.CdEndTime != 0 {
			fields["cd_time"] = tools.Timestamp2time(shm_user_item.CdEndTime)
		}
		err := tt.Model(&db.DbItem{}).Where("id = ? AND uid = ? AND cell = ? AND type = ?", shm_user_item.Id.NewVal, uid, index, shm_user_item.Type).Updates(fields).Error
		if err != nil {
			return err
		}
		*ss = shm_user_item.Id.Status
	}
	return nil
}

func MD_user_items(tt *gorm.DB, shm_user *sharemem.User, ss *MD_status) error {
	var j int16
	for j = 0; j < sharemem.USER_ITEM_NORMAL; j++ {
		res := MD_user_item(tt, &(shm_user.Item.Normal[j]), shm_user.Id.NewVal, j, &(ss.update_item.Normal[j]))
		if res != nil {
			return res
		}
	}
	for j = 0; j < sharemem.USER_ITEM_SPECIAL; j++ {
		res := MD_user_item(tt, &(shm_user.Item.Special[j]), shm_user.Id.NewVal, j, &(ss.update_item.Special[j]))
		if res != nil {
			return res
		}
	}
	return nil
}

func MD_user_equip(tt *gorm.DB, userEquip *sharemem.Equip, uid int64, index int16, ss *uint32) error {
	if userEquip.Id.NewVal != userEquip.Id.OldVal {
		if userEquip.Id.NewVal > 0 {
			jewelListJson, err := json.Marshal(userEquip.JewelList)
			if err != nil {
				return err
			}
			skillListJson, err := json.Marshal(userEquip.SkillList)
			if err != nil {
				return err
			}
			dbEquip := &db.DbEquip{
				Id:         userEquip.Id.NewVal,
				Uid:        uid,
				Cell:       index,
				Type:       db.EquipTypeNormal,
				Level:      userEquip.Level,
				Exp:        userEquip.Exp,
				LevelGroup: userEquip.LevelGroup,
				RoleId:     userEquip.RoleId,
				JewelList:  string(jewelListJson),
				SkillList:  string(skillListJson),
			}
			err = tt.Create(dbEquip).Error
			if err != nil {
				return err
			}
		}
		if userEquip.Id.OldVal > 0 {
			// delelte
			dbEquip := &db.DbEquip{
				Id:   userEquip.Id.OldVal,
				Uid:  uid,
				Cell: index,
				Type: db.EquipTypeNormal,
			}
			err := tt.Where("id = ? and uid = ? and cell = ? and type = ?", userEquip.Id.OldVal, uid, index, db.EquipTypeNormal).Delete(dbEquip).Error
			if err != nil {
				return err
			}
		}
		*ss = math.MaxUint32
	} else if userEquip.Id.Status != 0 {
		// update
		fields := make(map[string]interface{}, 7)
		fields["level"] = userEquip.Level
		fields["exp"] = userEquip.Exp
		fields["level_group"] = userEquip.LevelGroup
		fields["role_id"] = userEquip.RoleId
		jewelList, _ := json.Marshal(userEquip.JewelList)
		fields["jewel_list"] = string(jewelList)
		skillList, _ := json.Marshal(userEquip.SkillList)
		fields["skill_list"] = string(skillList)
		err := tt.Model(&db.DbEquip{}).Where("id = ? AND uid = ? AND cell = ?", userEquip.Id.NewVal, uid, index).Updates(fields).Error
		if err != nil {
			return err
		}
		*ss = userEquip.Id.Status
	}
	return nil
}

func MD_user_equip_jewel(tt *gorm.DB, userEquipJewel *sharemem.EquipJewel, uid int64, index int16, ss *uint32) error {
	if userEquipJewel.Id.NewVal != userEquipJewel.Id.OldVal {
		if userEquipJewel.Id.NewVal > 0 {
			// insert
			dbEquip := &db.DbEquip{
				Id:   userEquipJewel.Id.NewVal,
				Uid:  uid,
				Cell: index,
				Type: db.EquipTypeJewel,
			}
			err := tt.Create(dbEquip).Error
			if err != nil {
				return err
			}
		}
		if userEquipJewel.Id.OldVal > 0 {
			// delelte
			dbEquip := &db.DbEquip{
				Id:   userEquipJewel.Id.OldVal,
				Uid:  uid,
				Cell: index,
				Type: db.EquipTypeJewel,
			}
			err := tt.Where("id = ? and uid = ? and cell = ? and type = ?", userEquipJewel.Id.OldVal, uid, index, db.EquipTypeJewel).Delete(dbEquip).Error
			if err != nil {
				return err
			}
		}
		*ss = math.MaxUint32
	} else if userEquipJewel.Id.Status != 0 {
		// update
		*ss = userEquipJewel.Id.Status
	}
	return nil
}

func MD_user_equips(tt *gorm.DB, shm_user *sharemem.User, ss *MD_status) error {
	for i := 0; i < sharemem.USER_EQUIP; i++ {
		res := MD_user_equip(tt, &(shm_user.Equip[i]), shm_user.GetUid(), int16(i), &(ss.update_equip[i]))
		if res != nil {
			return res
		}
	}
	for i := 0; i < sharemem.USER_EQUIP_JEWEL; i++ {
		res := MD_user_equip_jewel(tt, &(shm_user.EquipJewel[i]), shm_user.GetUid(), int16(i), &(ss.update_equip_jewel[i]))
		if res != nil {
			return res
		}
	}
	return nil
}

func MD_user_team(tt *gorm.DB, shm_user *sharemem.User, ss *MD_status) error {
	for j := 0; j < sharemem.TEAM_MAX; j++ {
		ss.update_team[j] = 0
		if shm_user.Team[j].Id.NewVal != shm_user.Team[j].Id.OldVal {
			// insert
			fightRoleList, err := json.Marshal(shm_user.Team[j].FightRoleList)
			if err != nil {
				return err
			}
			assistRoleList, err := json.Marshal(shm_user.Team[j].AssistRoleList)
			if err != nil {
				return err
			}
			dbTeam := &db.DbTeam{
				Id:             shm_user.Team[j].Id.NewVal,
				Uid:            shm_user.Id.NewVal,
				Name:           shm_user.Team[j].GetName(),
				FightRoleList:  string(fightRoleList),
				AssistRoleList: string(assistRoleList),
			}
			err = tt.Create(dbTeam).Error
			if err != nil {
				return err
			}
			ss.update_team[j] = math.MaxUint32
		} else if shm_user.Team[j].Id.Status != 0 {
			// update
			fightRoleList, err := json.Marshal(shm_user.Team[j].FightRoleList)
			if err != nil {
				return err
			}
			assistRoleList, err := json.Marshal(shm_user.Team[j].AssistRoleList)
			if err != nil {
				return err
			}
			fields := make(map[string]interface{}, 3)
			fields["name"] = shm_user.Team[j].GetName()
			fields["fight_role_list"] = fightRoleList
			fields["assist_role_list"] = assistRoleList
			err = tt.Model(&db.DbTeam{}).Where("id = ? AND uid = ?", shm_user.Team[j].Id.NewVal, shm_user.Id.NewVal).Updates(fields).Error
			if err != nil {
				return err
			}
			ss.update_team[j] = shm_user.Team[j].Id.Status
		}
	}
	return nil
}

func MD_user_mail(tt *gorm.DB, user *sharemem.User, ss *MD_status) error {
	for i := 0; i < sharemem.MAIL_MAX; i++ {
		ss.update_mail[i] = 0
		if user.Mail[i].Id.NewVal != user.Mail[i].Id.OldVal {
			if user.Mail[i].Id.NewVal > 0 {
				// insert
				itemListJson, err := json.Marshal(user.Mail[i].ItemList)
				if err != nil {
					return err
				}
				dbMail := &db.DbMail{
					Id:              user.Mail[i].Id.NewVal,
					Uid:             user.GetUid(),
					Title:           user.Mail[i].GetTitle(),
					Content:         user.Mail[i].GetContent(),
					Sender:          user.Mail[i].GetSender(),
					SendTime:        user.Mail[i].SendTime,
					ExpireTime:      user.Mail[i].ExpireTime,
					IsRead:          user.Mail[i].IsRead,
					IsAttachmentGot: user.Mail[i].IsAttachmentGot,
					IsImportance:    user.Mail[i].IsImportance,
					ItemList:        string(itemListJson),
				}
				err = tt.Create(dbMail).Error
				if err != nil {
					return nil
				}
			}
			if user.Mail[i].Id.OldVal > 0 {
				// delelte
				dbMail := &db.DbMail{
					Id:  user.Mail[i].Id.OldVal,
					Uid: user.GetUid(),
				}
				err := tt.Where("id = ? and uid = ?", user.Mail[i].Id.OldVal, user.GetUid()).Delete(dbMail).Error
				if err != nil {
					return err
				}
			}
			ss.update_mail[i] = math.MaxUint32
		} else if user.Mail[i].Id.Status != 0 {
			// update
			fields := make(map[string]interface{}, 2)
			fields["is_read"] = user.Mail[i].IsRead
			fields["is_attachment_got"] = user.Mail[i].IsAttachmentGot
			err := tt.Model(&db.DbMail{}).Where("id = ? AND uid = ?", user.Mail[i].Id.NewVal, user.GetUid()).Updates(fields).Error
			if err != nil {
				return err
			}
			ss.update_mail[i] = user.Mail[i].Id.Status
		}
	}
	return nil
}

func MD_user_home(tt *gorm.DB, user *sharemem.User, ss *MD_status) error {
	ss.update_home = 0
	if user.UserHome.Id.NewVal != user.UserHome.Id.OldVal {
		if user.UserHome.Id.NewVal > 0 {
			unlockBuildingJson, err := json.Marshal(user.UserHome.UnlockBuildingList)
			if err != nil {
				return err
			}
			dbHome := &db.DbUserHome{
				Id:             user.UserHome.Id.NewVal,
				Uid:            user.GetUid(),
				Exp:            user.UserHome.Exp,
				Level:          user.UserHome.Level,
				UnlockBuilding: string(unlockBuildingJson),
			}
			err = tt.Create(dbHome).Error
			if err != nil {
				return nil
			}
		}
	} else if user.UserHome.Id.Status != 0 {
		fields := make(map[string]interface{}, 3)
		fields["level"] = user.UserHome.Level
		fields["exp"] = user.UserHome.Exp
		unlockBuildingJson, err := json.Marshal(user.UserHome.UnlockBuildingList)
		if err != nil {
			return err
		}
		fields["unlock_building"] = string(unlockBuildingJson)
		err = tt.Model(&db.DbUserHome{}).Where("id = ? AND uid = ?", user.UserHome.Id.NewVal, user.GetUid()).Updates(fields).Error
		if err != nil {
			return err
		}
		ss.update_home = user.UserHome.Id.Status
	}
	return nil
}

func MD_user_home_building(tt *gorm.DB, user *sharemem.User, ss *MD_status) error {
	for i := 0; i < sharemem.BUILDING_MAX; i++ {
		ss.update_home_building[i] = 0
		if user.UserHome.BuildingList[i].BuildingUuid.NewVal != user.UserHome.BuildingList[i].BuildingUuid.OldVal {
			if user.UserHome.BuildingList[i].BuildingUuid.NewVal > 0 {
				// insert
				farmListJson, err := json.Marshal(user.UserHome.BuildingList[i].Farm)
				if err != nil {
					return err
				}
				factoryListJson, err := json.Marshal(user.UserHome.BuildingList[i].Factory)
				if err != nil {
					return err
				}
				dbHomeBuilding := &db.DbUserHomeBuilding{
					BuildingUuid: user.UserHome.BuildingList[i].BuildingUuid.NewVal,
					Uid:          user.GetUid(),
					BuildingId:   user.UserHome.BuildingList[i].BuildingId,
					PosX:         user.UserHome.BuildingList[i].PosX,
					PosY:         user.UserHome.BuildingList[i].PosY,
					PosZ:         user.UserHome.BuildingList[i].PosZ,
					Level:        user.UserHome.BuildingList[i].Level,
					Farm:         string(farmListJson),
					Factory:      string(factoryListJson),
				}
				err = tt.Create(dbHomeBuilding).Error
				if err != nil {
					return nil
				}
			}
			if user.UserHome.BuildingList[i].BuildingUuid.OldVal > 0 {
				// delelte
				dbHomeBuilding := &db.DbUserHomeBuilding{
					BuildingUuid: user.UserHome.BuildingList[i].BuildingUuid.OldVal,
					Uid:          user.GetUid(),
				}
				err := tt.Where("building_uuid = ? and uid = ?", user.UserHome.BuildingList[i].BuildingUuid.OldVal, user.GetUid()).Delete(dbHomeBuilding).Error
				if err != nil {
					return err
				}
			}
			ss.update_home_building[i] = math.MaxUint32
		} else if user.UserHome.BuildingList[i].BuildingUuid.Status != 0 {
			// update
			fields := make(map[string]interface{}, 6)
			fields["pos_x"] = user.UserHome.BuildingList[i].PosX
			fields["pos_y"] = user.UserHome.BuildingList[i].PosY
			fields["pos_z"] = user.UserHome.BuildingList[i].PosZ
			fields["level"] = user.UserHome.BuildingList[i].Level

			farmListJson, err := json.Marshal(user.UserHome.BuildingList[i].Farm)
			if err != nil {
				return err
			}
			factoryListJson, err := json.Marshal(user.UserHome.BuildingList[i].Factory)
			if err != nil {
				return err
			}
			fields["farm"] = farmListJson
			fields["factory"] = factoryListJson
			err = tt.Model(&db.DbUserHomeBuilding{}).Where("id = ? AND uid = ?", user.UserHome.BuildingList[i].BuildingUuid.NewVal, user.GetUid()).Updates(fields).Error
			if err != nil {
				return err
			}
			ss.update_home_building[i] = user.Mail[i].Id.Status
		}
	}
	return nil
}

func MD_user_data(tt *gorm.DB, user *sharemem.User) error {
	sceneData, err := json.Marshal(user.UserScene)
	if err != nil {
		logger.Error("marshal user scene error: %v, uid: %v", err, user.GetUid())
		return err
	}
	questData, err := json.Marshal(user.UserQuest)
	if err != nil {
		logger.Error("marshal user quest error: %v, uid: %v", err, user.GetUid())
		return err
	}
	shopData, err := json.Marshal(user.UserShop)
	if err != nil {
		logger.Error("marshal user shop error: %v, uid: %v", err, user.GetUid())
		return err
	}
	gachaData, err := json.Marshal(user.UserGacha)
	if err != nil {
		logger.Error("marshal user gacha error: %v, uid: %v", err, user.GetUid())
		return err
	}
	codexData, err := json.Marshal(user.UserCodex)
	if err != nil {
		logger.Error("marshal user codex error: %v, uid: %v", err, user.GetUid())
		return err
	}
	weaponData, err := json.Marshal(user.UserWeapon)
	if err != nil {
		logger.Error("marshal user weapon error: %v, uid: %v", err, user.GetUid())
		return err
	}
	//homeData, err := json.Marshal(user.UserHome)
	//if err != nil {
	//	logger.Error("marshal user home error: %v, uid: %v", err, user.GetUid())
	//	return err
	//}
	activityData, err := json.Marshal(user.UserActivity)
	if err != nil {
		logger.Error("marshal user activity error: %v, uid: %v", err, user.GetUid())
		return err
	}
	err = tt.Clauses(clause.OnConflict{
		Columns: []clause.Column{{Name: "uid"}},
		DoUpdates: clause.AssignmentColumns([]string{
			"scene_data",
			"quest_data",
			"shop_data",
			"gacha_data",
			"codex_data",
			"weapon_data",
			//"home_data",
			"activity_data",
			"scene_id",
			"team_id",
			"client_data",
			"curr_mail_id",
			"global_mail_id",
			"timer_mail_id",
			"tower_area",
			"tower_level",
			"tower_pass_area",
			"tower_pass_level",
			"tower_pass_time",
		}),
	}).Create(&db.DbUserData{
		Uid:        user.GetUid(),
		NickName:   user.GetName(),
		SceneData:  string(sceneData),
		QuestData:  string(questData),
		ShopData:   string(shopData),
		GachaData:  string(gachaData),
		CodexData:  string(codexData),
		WeaponData: string(weaponData),
		//HomeData:       string(homeData),
		ActivityData:   string(activityData),
		SceneId:        user.SceneId,
		TeamId:         user.TeamId,
		ClientData:     user.GetClientData(),
		CurrMailId:     user.CurrMailId,
		GlobalMailId:   user.GlobalMailId,
		TimerMailId:    user.TimerMailId,
		TowerArea:      user.UserActivity.TowerArea,
		TowerLevel:     user.UserActivity.TowerLevel,
		TowerPassArea:  user.UserActivity.TowerPassArea,
		TowerPassLevel: user.UserActivity.TowerPassLevel,
		TowerPassTime:  user.UserActivity.TowerPassTime,
	}).Error
	if err != nil {
		logger.Error("db write user data error: %v, uid: %v", err, user.GetUid())
		return err
	}
	return nil
}

func Sync_shm(ss *MD_status, shm_user *sharemem.User, index int32) {
	if ss.update_user == math.MaxUint32 {
		shm_user.Id.OldVal = shm_user.Id.NewVal
	} else if ss.update_user != 0 {
		atomic.AddUint32(&(shm_user.Id.Status), -ss.update_user)
	}
	if ss.gem_value != 0 {
		atomic.AddInt32(&(shm_user.Gem.OldVal), ss.gem_value)
	}

	var j int32
	// role表
	for j = 0; j < sharemem.ROLE_MAX; j++ {
		if ss.update_role[j] == math.MaxUint32 {
			shm_user.Role[j].Id.OldVal = shm_user.Role[j].Id.NewVal
		} else if ss.update_role[j] != 0 {
			atomic.AddUint32(&(shm_user.Role[j].Id.Status), -ss.update_role[j])
		}
	}
	// item表
	for j = 0; j < sharemem.USER_ITEM_NORMAL; j++ {
		if ss.update_item.Normal[j] == math.MaxUint32 {
			shm_user.Item.Normal[j].Id.OldVal = shm_user.Item.Normal[j].Id.NewVal
		} else if ss.update_item.Normal[j] != 0 {
			atomic.AddUint32(&(shm_user.Item.Normal[j].Id.Status), -ss.update_item.Normal[j])
		}
	}
	for j = 0; j < sharemem.USER_ITEM_SPECIAL; j++ {
		if ss.update_item.Special[j] == math.MaxUint32 {
			shm_user.Item.Special[j].Id.OldVal = shm_user.Item.Special[j].Id.NewVal
		} else if ss.update_item.Special[j] != 0 {
			atomic.AddUint32(&(shm_user.Item.Special[j].Id.Status), -ss.update_item.Special[j])
		}
	}

	// equip表
	for j = 0; j < sharemem.USER_EQUIP; j++ {
		if ss.update_equip[j] == math.MaxUint32 {
			shm_user.Equip[j].Id.OldVal = shm_user.Equip[j].Id.NewVal
		} else if ss.update_equip[j] != 0 {
			atomic.AddUint32(&(shm_user.Equip[j].Id.Status), -ss.update_equip[j])
		}
	}

	for j = 0; j < sharemem.USER_EQUIP_JEWEL; j++ {
		if ss.update_equip_jewel[j] == math.MaxUint32 {
			shm_user.EquipJewel[j].Id.OldVal = shm_user.EquipJewel[j].Id.NewVal
		} else if ss.update_equip_jewel[j] != 0 {
			atomic.AddUint32(&(shm_user.EquipJewel[j].Id.Status), -ss.update_equip_jewel[j])
		}
	}

	// team表
	for j = 0; j < sharemem.TEAM_MAX; j++ {
		if ss.update_team[j] == math.MaxUint32 {
			shm_user.Team[j].Id.OldVal = shm_user.Team[j].Id.NewVal
		} else if ss.update_team[j] != 0 {
			atomic.AddUint32(&(shm_user.Team[j].Id.Status), -ss.update_team[j])
		}
	}

	// mail表
	for j = 0; j < sharemem.MAIL_MAX; j++ {
		if ss.update_mail[j] == math.MaxUint32 {
			shm_user.Mail[j].Id.OldVal = shm_user.Mail[j].Id.NewVal
		} else if ss.update_mail[j] != 0 {
			atomic.AddUint32(&(shm_user.Mail[j].Id.Status), -ss.update_mail[j])
		}
	}

	if ss.update_home == math.MaxUint32 {
		shm_user.UserHome.Id.OldVal = shm_user.UserHome.Id.NewVal
	} else if ss.update_home != 0 {
		atomic.AddUint32(&(shm_user.UserHome.Id.Status), -ss.update_home)
	}

	// mail表
	for j = 0; j < sharemem.BUILDING_MAX; j++ {
		if ss.update_home_building[j] == math.MaxUint32 {
			shm_user.UserHome.BuildingList[j].BuildingUuid.OldVal = shm_user.UserHome.BuildingList[j].BuildingUuid.NewVal
		} else if ss.update_home_building[j] != 0 {
			atomic.AddUint32(&(shm_user.UserHome.BuildingList[j].BuildingUuid.Status), -ss.update_home_building[j])
		}
	}
}

// 内存数据同步到数据库

func MD_User(i int32, flag bool) error {
	var myshm = sharemem.MyShm
	//var res int16
	var ss MD_status
	if myshm.Usr[i].Id.NewVal == 0 {
		logger.Error("invalid uid, index: %v", i)
		return nil
	}
	logger.Info("save user, uid: %v", myshm.Usr[i].GetUid())
	tt := db.Conn.Begin()
	// user表
	res := MD_user(tt, &(myshm.Usr[i]), &ss)
	if res != nil {
		tt.Rollback()
		return res
	}
	// user_role表
	res = MD_user_role(tt, &(myshm.Usr[i]), &ss)
	if res != nil {
		tt.Rollback()
		return res
	}
	// user_item表
	res = MD_user_items(tt, &(myshm.Usr[i]), &ss)
	if res != nil {
		tt.Rollback()
		return res
	}
	// user_equip表
	res = MD_user_equips(tt, &(myshm.Usr[i]), &ss)
	if res != nil {
		tt.Rollback()
		return res
	}
	// user_team表
	res = MD_user_team(tt, &(myshm.Usr[i]), &ss)
	if res != nil {
		tt.Rollback()
		return res
	}
	// user_mail表
	res = MD_user_mail(tt, &(myshm.Usr[i]), &ss)
	if res != nil {
		tt.Rollback()
		return res
	}
	// user_home表
	res = MD_user_home(tt, &(myshm.Usr[i]), &ss)
	if res != nil {
		tt.Rollback()
		return res
	}
	// user_home_building表
	res = MD_user_home_building(tt, &(myshm.Usr[i]), &ss)
	if res != nil {
		tt.Rollback()
		return res
	}

	if flag {
		// user_data
		res = MD_user_data(tt, &(myshm.Usr[i]))
		if res != nil {
			tt.Rollback()
			return res
		}
	}
	tt.Commit()
	// 同步处理共享内存
	Sync_shm(&ss, &(myshm.Usr[i]), i)
	return nil
}

func DeleteUser(uid int64) error {
	tx := db.Conn.Begin()
	err := tx.Exec("DELETE FROM `user` WHERE `id` = ?", uid).Error
	if err != nil {
		tx.Rollback()
		return err
	}
	err = tx.Exec("DELETE FROM `user_data` WHERE `uid` = ?", uid).Error
	if err != nil {
		tx.Rollback()
		return err
	}
	err = tx.Exec("DELETE FROM `user_equip` WHERE `uid` = ?", uid).Error
	if err != nil {
		tx.Rollback()
		return err
	}
	err = tx.Exec("DELETE FROM `user_item` WHERE `uid` = ?", uid).Error
	if err != nil {
		tx.Rollback()
		return err
	}
	err = tx.Exec("DELETE FROM `user_mail` WHERE `uid` = ?", uid).Error
	if err != nil {
		tx.Rollback()
		return err
	}
	err = tx.Exec("DELETE FROM `user_role` WHERE `uid` = ?", uid).Error
	if err != nil {
		tx.Rollback()
		return err
	}
	err = tx.Exec("DELETE FROM `user_team` WHERE `uid` = ?", uid).Error
	if err != nil {
		tx.Rollback()
		return err
	}
	err = tx.Exec("DELETE FROM `user_home` WHERE `uid` = ?", uid).Error
	if err != nil {
		tx.Rollback()
		return err
	}
	err = tx.Exec("DELETE FROM `user_home_building` WHERE `uid` = ?", uid).Error
	if err != nil {
		tx.Rollback()
		return err
	}
	err = tx.Commit().Error
	if err != nil {
		return err
	}
	return nil
}
